/**********************************************************************
  Copyright(c) 2021-2023 Arm Corporation All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the
      distribution.
    * Neither the name of Arm Corporation nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ipsec-mb.h"
#include "include/snow3g.h"
#include "include/zuc_internal.h"

#include "include/cpu_feature.h"
#include "include/error.h"
#include "clear_regs_mem_aarch64.h"
#include "include/noaesni.h"
#include "include/ipsec_ooo_mgr.h"
#include "arch_aarch64_sve256.h"
#include "arch_aarch64.h"

#include "include/ooo_mgr_reset.h"

#define SUBMIT_JOB                  submit_job_aarch64_sve256
#define FLUSH_JOB                   flush_job_aarch64_sve256
#define QUEUE_SIZE                  queue_size_aarch64_sve256
#define SUBMIT_JOB_NOCHECK          submit_job_nocheck_aarch64_sve256
#define GET_NEXT_JOB                get_next_job_aarch64_sve256
#define GET_COMPLETED_JOB           get_completed_job_aarch64_sve256
#define GET_NEXT_BURST              get_next_burst_aarch64_sve256
#define SUBMIT_BURST                submit_burst_aarch64_sve256
#define SUBMIT_BURST_NOCHECK        submit_burst_nocheck_aarch64_sve256
#define FLUSH_BURST                 flush_burst_aarch64_sve256
#define SUBMIT_CIPHER_BURST         submit_cipher_burst_aarch64_sve256
#define SUBMIT_CIPHER_BURST_NOCHECK submit_cipher_burst_nocheck_aarch64_sve256
#define SUBMIT_HASH_BURST           submit_hash_burst_aarch64_sve256
#define SUBMIT_HASH_BURST_NOCHECK   submit_hash_burst_nocheck_aarch64_sve256
#define SET_SUITE_ID_FN             set_suite_id_aarch64_sve256

#define SUBMIT_JOB_ZUC_EEA3         submit_job_zuc_eea3_aarch64
#define FLUSH_JOB_ZUC_EEA3          flush_job_zuc_eea3_aarch64
#define SUBMIT_JOB_ZUC_EIA3         submit_job_zuc_eia3_aarch64
#define FLUSH_JOB_ZUC_EIA3          flush_job_zuc_eia3_aarch64
#define SUBMIT_JOB_ZUC256_EEA3      submit_job_zuc256_eea3_aarch64
#define FLUSH_JOB_ZUC256_EEA3       flush_job_zuc256_eea3_aarch64
#define SUBMIT_JOB_ZUC256_EIA3      submit_job_zuc256_eia3_aarch64
#define FLUSH_JOB_ZUC256_EIA3       flush_job_zuc256_eia3_aarch64
#define SUBMIT_JOB_SNOW3G_UEA2      submit_job_snow3g_uea2_aarch64_sve256
#define FLUSH_JOB_SNOW3G_UEA2       flush_job_snow3g_uea2_aarch64_sve256
#define SUBMIT_JOB_SNOW3G_UIA2      submit_job_snow3g_uia2_aarch64_sve256
#define FLUSH_JOB_SNOW3G_UIA2       flush_job_snow3g_uia2_aarch64_sve256

static void reset_ooo_mgrs(IMB_MGR *state)
{
        /* Init ZUC out-of-order fields */
        ooo_mgr_zuc_reset(state->zuc_eea3_ooo, 4);
        ooo_mgr_zuc_reset(state->zuc_eia3_ooo, 4);
        ooo_mgr_zuc_reset(state->zuc256_eea3_ooo, 4);
        ooo_mgr_zuc_reset(state->zuc256_eia3_ooo, 4);

        /* Init SNOW3G-UEA out-of-order fields */
        ooo_mgr_snow3g_reset(state->snow3g_uea2_ooo, 8);

        /* Init SNOW3G-UIA out-of-order fields */
        ooo_mgr_snow3g_reset(state->snow3g_uia2_ooo, 8);
}

IMB_DLL_LOCAL void
init_mb_mgr_aarch64_sve256_internal(IMB_MGR *state, const int reset_mgrs)
{
#ifdef SAFE_PARAM
        if (state == NULL) {
                imb_set_errno(NULL, IMB_ERR_NULL_MBMGR);
                return;
        }
#endif

        /* reset error status */
        imb_set_errno(state, 0);

        state->features = cpu_feature_adjust(state->flags,
                                             cpu_feature_detect());

        /* Set architecture for future checks */
        state->used_arch = (uint32_t) IMB_ARCH_SVE256;

        if (!(state->features & IMB_FEATURE_AESNI)) {
                init_mb_mgr_aarch64_no_aesni(state);
                return;
        }

        if (reset_mgrs) {
                reset_ooo_mgrs(state);

                /* Init "in order" components */
                state->next_job = 0;
                state->earliest_job = -1;
        }

        /* set AARCH64 handlers */
        state->get_next_job                = get_next_job_aarch64_sve256;
        state->submit_job                  = submit_job_aarch64_sve256;
        state->submit_job_nocheck          = submit_job_nocheck_aarch64_sve256;
        state->get_completed_job           = get_completed_job_aarch64_sve256;
        state->flush_job                   = flush_job_aarch64_sve256;
        state->queue_size                  = queue_size_aarch64_sve256;
        state->get_next_burst              = GET_NEXT_BURST;
        state->submit_burst                = SUBMIT_BURST;
        state->submit_burst_nocheck        = SUBMIT_BURST_NOCHECK;
        state->flush_burst                 = FLUSH_BURST;
        state->submit_cipher_burst         = SUBMIT_CIPHER_BURST;
        state->submit_cipher_burst_nocheck = SUBMIT_CIPHER_BURST_NOCHECK;
        state->submit_hash_burst           = SUBMIT_HASH_BURST;
        state->submit_hash_burst_nocheck   = SUBMIT_HASH_BURST_NOCHECK;
        state->set_suite_id                = SET_SUITE_ID_FN;

        state->eea3_1_buffer               = zuc_eea3_1_buffer_aarch64;
        state->eea3_4_buffer               = zuc_eea3_4_buffer_aarch64;
        state->eea3_n_buffer               = zuc_eea3_n_buffer_aarch64;
        state->zuc256_eea3_1_buffer        = zuc256_eea3_1_buffer_aarch64;
        state->zuc256_eea3_n_buffer        = zuc256_eea3_n_buffer_aarch64;
        state->eia3_1_buffer               = zuc_eia3_1_buffer_aarch64;
        state->eia3_n_buffer               = zuc_eia3_n_buffer_aarch64;
        state->zuc256_eia3_1_buffer        = zuc256_eia3_1_buffer_aarch64;
        state->zuc256_eia3_n_buffer        = zuc256_eia3_n_buffer_aarch64;

        state->snow3g_f8_1_buffer_bit      = snow3g_f8_1_buffer_bit_aarch64_sve256;
        state->snow3g_f8_1_buffer          = snow3g_f8_1_buffer_aarch64_sve256;
        state->snow3g_f8_2_buffer          = snow3g_f8_2_buffer_aarch64_sve256;
        state->snow3g_f8_4_buffer          = snow3g_f8_4_buffer_aarch64_sve256;
        state->snow3g_f8_8_buffer          = snow3g_f8_8_buffer_aarch64_sve256;
        state->snow3g_f8_n_buffer          = snow3g_f8_n_buffer_aarch64_sve256;
        state->snow3g_f8_4_buffer_multikey = snow3g_f8_4_buffer_multikey_aarch64_sve256;
        state->snow3g_f8_8_buffer_multikey = snow3g_f8_8_buffer_multikey_aarch64_sve256;
        state->snow3g_f8_n_buffer_multikey = snow3g_f8_n_buffer_multikey_aarch64_sve256;
        state->snow3g_f9_1_buffer          = snow3g_f9_1_buffer_aarch64_sve256;
        state->snow3g_init_key_sched       = snow3g_init_key_sched_aarch64_sve256;
        state->snow3g_key_sched_size       = snow3g_key_sched_size_aarch64_sve256;

        state->crc32_wimax_ofdma_data      = crc32_wimax_ofdma_data_aarch64;
}

void
init_mb_mgr_aarch64_sve256(IMB_MGR *state)
{
        IMB_ASSERT(state->features & IMB_FEATURE_SVE256);
        init_mb_mgr_aarch64_sve256_internal(state, 1);
}
#include "mb_mgr_code.h"
